"""
Anthropic Claude流式输出功能实现
支持Claude模型的流式文本生成
"""
from typing import Dict, Any, List, Optional, Generator
import json
import logging

from ...capabilities.streaming import StreamingCapability

logger = logging.getLogger("llm.anthropic.stream")

class AnthropicStreaming(StreamingCapability):
	"""Anthropic Claude的流式输出实现"""
	
	def _initialize(self) -> None:
		"""初始化流式功能"""
		self.supported = True
		logger.debug("初始化Anthropic流式输出功能")
	
	def is_supported(self) -> bool:
		"""
		检查是否支持流式输出
		
		Returns:
			是否支持流式输出
		"""
		# Claude 3模型系列全面支持流式输出
		return self.supported
		
	def stream_response(self, messages: List[Dict[str, Any]], **kwargs) -> Generator[str, None, None]:
		"""
		生成流式响应
		
		Args:
			messages: 消息列表
			**kwargs: 额外的提供商特定参数
			
		Returns:
			字符串流生成器
		"""
		logger.debug("开始Anthropic流式生成")
		
		try:
			# 获取Anthropic库和客户端
			anthropic_sdk_available = False
			try:
				import anthropic
				anthropic_sdk_available = True
			except ImportError:
				logger.warning("未安装anthropic SDK，将使用直接API调用")
				
			# 获取参数
			params = {
				"model": self.provider.model,
				"messages": messages,
				"temperature": self.provider.temperature,
				"max_tokens": self.provider.max_tokens,
				**kwargs
			}
			
			# 选择流式方法
			if anthropic_sdk_available and hasattr(self.provider, 'client') and self.provider.client:
				# 使用官方SDK的流式API
				client = self.provider.client
				
				with client.messages.stream(
					**params
				) as stream:
					for text in stream.text_stream:
						yield text
			else:
				# 直接API调用
				import requests
				
				headers = {
					"x-api-key": self.provider.api_key,
					"anthropic-version": "2023-06-01",
					"content-type": "application/json"
				}
				
				stream_params = {**params, "stream": True}
				
				response = self.provider._call_with_retry(
					requests.post,
					"https://api.anthropic.com/v1/messages",
					headers=headers,
					json=stream_params,
					stream=True
				)
				
				if response.status_code != 200:
					raise Exception(f"API请求失败: {response.status_code} {response.text}")
					
				for line in response.iter_lines():
					if line:
						if line.startswith(b"data: "):
							line = line[6:]  # 去掉 "data: " 前缀
							if line.strip() == b"[DONE]":
								break
							try:
								chunk = json.loads(line)
								delta = self.process_chunk(chunk)
								if delta:
									yield delta
							except json.JSONDecodeError:
								pass
								
		except Exception as e:
			logger.error(f"流式生成过程中出错: {str(e)}")
			yield f"\n[错误: {str(e)}]"
			
		logger.debug("Anthropic流式生成结束")
	
	def process_chunk(self, chunk: Dict[str, Any]) -> Optional[str]:
		"""
		处理单个响应数据块
		
		Args:
			chunk: 响应数据块
			
		Returns:
			处理后的文本，如果数据块不包含文本则返回None
		"""
		try:
			# Anthropic的流式响应包含content字段
			if "content" in chunk and len(chunk["content"]) > 0:
				content_item = chunk["content"][0]
				if content_item.get("type") == "text":
					return content_item.get("text", "")
		except Exception as e:
			logger.error(f"处理流式数据块时出错: {str(e)}")
			
		return None
		
	def detect_finish_reason(self, chunk: Dict[str, Any]) -> Optional[str]:
		"""
		检测数据块中的完成原因
		
		Args:
			chunk: 响应数据块
			
		Returns:
			完成原因，如果数据块不包含完成原因则返回None
		"""
		try:
			# Anthropic的流式响应中的停止原因
			if "stop_reason" in chunk:
				return chunk["stop_reason"]
		except Exception as e:
			logger.error(f"检测完成原因时出错: {str(e)}")
			
		return None
	
	def detect_tool_calls(self, chunk: Dict[str, Any]) -> Optional[List[Dict[str, Any]]]:
		"""
		检测数据块中是否包含工具调用
		
		Args:
			chunk: 响应数据块
			
		Returns:
			工具调用列表，如果没有则返回None
		"""
		# 检查是否有工具调用功能
		if not self.provider.has_capability("tool_calls"):
			return None
			
		try:
			stop_reason = self.detect_finish_reason(chunk)
			
			# 只有当finish_reason为tool_calls时才有工具调用
			if stop_reason == "tool_use":
				# Anthropic的工具调用格式
				if "content" in chunk:
					for content_item in chunk["content"]:
						if content_item.get("type") == "tool_use":
							return [content_item]
		except Exception as e:
			logger.error(f"检测工具调用时出错: {str(e)}")
			
		return None
